package ru.magicreader.client.controller;

import ru.magicreader.client.model.Feed;
import ru.magicreader.client.model.Settings;
import ru.magicreader.client.model.User;

import com.google.gwt.core.client.GWT;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.user.client.Window;

public class MainState {
	private static final String NEW_FEED_REQUEST_URL = GWT.getModuleBaseURL() + "feedServlet?action=newFeed";
	private static final String MODIFY_FEED_REQUEST_URL = GWT.getModuleBaseURL() + "feedServlet?action=modifyFeed";
	private static final String DELETE_FEED_REQUEST_URL = GWT.getModuleBaseURL() + "feedServlet?action=deleteFeed";
	private static final String GET_USER_REQUEST_URL = GWT.getModuleBaseURL() + "feedServlet?action=getUser";
	private static final String UPDATE_FEEDS_REQUEST_URL = GWT.getModuleBaseURL() + "feedServlet?action=updateFeeds";
	private static final String MODIFY_SETTINGS_REQUEST_URL = GWT.getModuleBaseURL() + "feedServlet?action=modifySettings";
	
	public interface MainStateHandler {
		public void newFeedError(String msg);

		public void newFeedOk(User user, Feed feed);

		public void deleteFeedOk(User user, String feedUrl);

		public void deleteFeedError(String msg);

		public void modifyFeedError(String msg);

		public void modifyFeedOk(User user, Feed feed);

		public void getUserOk(User user);

		public void getUserError(String msg);

		public void updateFeedsOk(User user);

		public void updateFeedsError(String msg);

		public void modifySettingsOk(User user, Settings settings);

		public void modifySettingsError(String msg);

		public void onInternalServerError(String response);
	}
	
	private User user;
	
	public MainState() {
	}

	public void newFeed(String feedUrl, boolean isImportant, final MainStateHandler handler) {
		if(!validate(feedUrl)) {
			handler.newFeedError("Illegal URL: " + feedUrl);
			return;
		}
		
		RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.POST, NEW_FEED_REQUEST_URL);
		try {
			requestBuilder.sendRequest(
					feedUrl + (isImportant ? "\nimportant=true" : ""), 
					new RequestCallback() {
				
						@Override
						public void onResponseReceived(Request request, Response response) {
							if(response.getStatusCode() == Response.SC_UNAUTHORIZED) {
								handler.newFeedError("Server replies: UNAUTHORIZED");
							}
							else if(response.getStatusCode() == Response.SC_OK) {
								Feed feed = Feed.fromJsonString(response.getText());
								user.getFeeds().push(feed);
								handler.newFeedOk(user, feed);
							}
							else {
								handler.newFeedError("Server replies: " + response.getStatusCode());
							}
						}
						
						@Override
						public void onError(Request request, Throwable exception) {
							handler.newFeedError("onError: " + exception);							
						}
					}
			);
		} catch (RequestException e) {
			handler.newFeedError("RequestException: " + e.getMessage());
		}
	}
	
	public void modifyFeed(final Feed feed, final MainStateHandler handler) {
		RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.POST, MODIFY_FEED_REQUEST_URL);
		try {
			requestBuilder.sendRequest(
					feed.getUrl() + "\n" +
					"important=" + feed.isImportant(), 
					new RequestCallback() 
				{
				
				@Override
				public void onResponseReceived(Request request, Response response) {
					if(response.getStatusCode() == Response.SC_UNAUTHORIZED) {
						handler.modifyFeedError("Server replies: UNAUTHORIZED");
					}
					else if(response.getStatusCode() == Response.SC_OK) {
						handler.modifyFeedOk(user, feed);
					}
					else {
						handler.modifyFeedError("Server replies: " + response.getStatusCode());
					}
				}
				
				@Override
				public void onError(Request request, Throwable exception) {
					handler.modifyFeedError("onError: " + exception);							
				}
			});
		} catch (RequestException e) {
			handler.modifyFeedError("RequestException: " + e.getMessage());
		}
	}
	
	public void deleteFeed(final String feedUrl, final MainStateHandler handler) {
		RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.POST, DELETE_FEED_REQUEST_URL);
		try {
			requestBuilder.sendRequest(feedUrl, new RequestCallback() {
				
				@Override
				public void onResponseReceived(Request request, Response response) {
					if(response.getStatusCode() == Response.SC_UNAUTHORIZED) {
						handler.deleteFeedError("Server replies: UNAUTHORIZED");
					}
					else if(response.getStatusCode() == Response.SC_OK) {
						handler.deleteFeedOk(user, feedUrl);
					}
					else {
						handler.deleteFeedError("Server replies: " + response.getStatusCode());
					}
				}
				
				@Override
				public void onError(Request request, Throwable exception) {
					handler.newFeedError("onError: " + exception);							
				}
			});
		} catch (RequestException e) {
			handler.newFeedError("RequestException: " + e.getMessage());
		}
	}
	
	public void getUser(final MainStateHandler handler) {
		String defaulturl = Window.Location.getParameter("defaulturl");
		RequestBuilder requestBuilder = new RequestBuilder(
				RequestBuilder.GET, 
				GET_USER_REQUEST_URL + (defaulturl != null ? "&defaulturl=" + defaulturl : "")
		);
		try {
			requestBuilder.sendRequest(null, new RequestCallback() {
				
				@Override
				public void onResponseReceived(Request request, Response response) {
					if(response.getStatusCode() == Response.SC_OK) {
						User user = User.fromJsonString(response.getText());
						handler.getUserOk(user);
						MainState.this.user = user;
					}
					else if(response.getStatusCode() == Response.SC_INTERNAL_SERVER_ERROR) {
						handler.onInternalServerError(response.getText());
					}
					else {
						handler.getUserError("Got non-OK response! Code: " + response.getStatusCode() + "\nData:\n" + response.getText());
					}
				}
				
				@Override
				public void onError(Request request, Throwable exception) {
					handler.getUserError("onError: " + exception);
				}						
			});
		} catch (RequestException e) {
			handler.getUserError("RequestException: " + e.getMessage());
		}
	}
	
	public void updateFeeds(final MainStateHandler handler) {
		RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.GET, UPDATE_FEEDS_REQUEST_URL);
		try {
			requestBuilder.sendRequest(null, new RequestCallback() {
				
				@Override
				public void onResponseReceived(Request request, Response response) {
					if(response.getStatusCode() == Response.SC_OK) {
						handler.updateFeedsOk(user);
					}
					else if(response.getStatusCode() == Response.SC_INTERNAL_SERVER_ERROR) {
						Window.alert("Got non-OK response! Code: " + response.getStatusCode() + "\nData:\n" + response.getText());
						Window.open(GWT.getHostPageBaseURL() + "ko-internal.html", "ko-internal.html", "");
					}
					else {
						handler.updateFeedsError("Got non-OK response! Code: " + response.getStatusCode() + "\nData:\n" + response.getText());
					}
				}
				
				@Override
				public void onError(Request request, Throwable exception) {
					handler.updateFeedsError("onError: " + exception);
				}						
			});
		} catch (RequestException e) {
			handler.updateFeedsError("RequestException: " + e.getMessage());
		}
	}

	private boolean validate(String feedUrl) {
		return feedUrl.length() > 0;
	}

	public void modifySettings(final Settings settings, final MainStateHandler handler) {
		RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.POST, MODIFY_SETTINGS_REQUEST_URL);
		try {
			requestBuilder.sendRequest(
					"nEntriesToShow=" + settings.getNEntriesToShow(), 
					new RequestCallback() 
				{
				
				@Override
				public void onResponseReceived(Request request, Response response) {
					if(response.getStatusCode() == Response.SC_UNAUTHORIZED) {
						handler.modifyFeedError("Server replies: UNAUTHORIZED");
					}
					else if(response.getStatusCode() == Response.SC_OK) {
						handler.modifySettingsOk(user, settings);
					}
					else {
						handler.modifySettingsError("Server replies: " + response.getStatusCode());
					}
				}
				
				@Override
				public void onError(Request request, Throwable exception) {
					handler.modifySettingsError("onError: " + exception);							
				}
			});
		} catch (RequestException e) {
			handler.modifySettingsError("RequestException: " + e.getMessage());
		}
	}	

}
